﻿Imports Microsoft.VisualBasic
Imports System.Net

Namespace WebApi

    Public Enum Type
        TWITTER
        FACEBOOK
        GOOGLE
        LINKEDIN
        RSS
        OPENSTREETMAP
        INSTAGRAM
        BUFFER
        KLOUT
    End Enum
    Namespace Net

        Public Class WebClient
            Inherits System.Net.WebClient

            Public Property oAuth As Oauth.Oauth
            Public Property oAuth2 As Oauth.Oauth2
            Public Property CookieContainer As System.Net.CookieContainer
            Public Property UserAgent As String
            Public Property Timeout As Integer
            Public Property StatusCode As Integer
            Public Property StatusCodeDescr As String
            Public Property RequestUri As Uri
            'Public Property ResponseUri As Uri
            Public Property Multipart As Boolean = False
            Public Property LastModified As Date = Date.MinValue
            Public Property ETag As String = ""

            Public Property postParams() As Dictionary(Of String, String)

            Public Sub New()
                Me.Timeout = 30 * 1000
                Me.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
                Me.CookieContainer = New CookieContainer()
                Me.postParams = New Dictionary(Of String, String)
                'm_cookieContainer.Add(New Net.Cookie("example",  "example_value", "/"))

            End Sub

            Protected Overrides Function GetWebRequest(address As Uri) As WebRequest

                '-----------------------------------
                ' QUERY
                '-----------------------------------

                'modifica query string oath2
                If Me.oAuth2 IsNot Nothing Then

                    Dim Uri As New UriBuilder(address)

                    Dim queryString = HttpUtility.ParseQueryString(address.Query)
                    'RequestField_AccessToken
                    queryString.Add(Me.oAuth2.RequestField_AccessToken, Me.oAuth2.access_token)

                    'request_visible_actions

                    Uri.Query = queryString.ToString

                    address = Uri.Uri

                End If


                Dim request As HttpWebRequest = MyBase.GetWebRequest(address)

                If Me.oAuth2 IsNot Nothing Then
                    request.Headers.Add("Authorization", "Bearer " & Me.oAuth2.access_token)
                End If

                Me.RequestUri = request.RequestUri
                'RefreshUserAgent()

                '-----------------------------------
                ' POST
                '-----------------------------------
                If Me.postParams.Count > 0 Then
                    request.Method = "POST"

                    Dim postBody As String = ""

                    If Multipart Then
                        Dim boundary = Now.ToLongTimeString
                        request.ContentType = SF("multipart/form-data;boundary={0}", boundary)

                        postBody =
                            "--" & boundary & vbCrLf &
                            "Content-Disposition: form-data; name=""status""" & vbCrLf & vbCrLf &
                            Me.postParams("status") & vbCrLf &
                            "--" & boundary & vbCrLf &
                            "Content-Disposition: form-data; name=""media[]""" & vbCrLf &
                            "Content-Transfer-Encoding: base64" & vbCrLf & vbCrLf &
                            Me.postParams("media[]") & vbCrLf &
                            "--" & boundary & "--" & vbCrLf

                    Else
                        request.ContentType = "application/x-www-form-urlencoded"


                        For Each postParam In Me.postParams
                            If postParam.Key <> "*" Then
                                postBody = postBody & String.Format("{0}={1}&", postParam.Key, postParam.Value)
                            Else
                                request.ContentType = "application/json"
                                postBody = postBody & String.Format("{0}", postParam.Value)
                            End If
                        Next

                    End If

                    Dim contentBytes = Encoding.UTF8.GetBytes(postBody)
                    Dim stream = request.GetRequestStream()
                    stream.Write(contentBytes, 0, contentBytes.Length)

                Else
                    request.Method = "GET"
                End If

                '-----------------------------------
                ' HEADER
                '-----------------------------------

                If Me.LastModified <> Date.MinValue Then
                    request.IfModifiedSince = Me.LastModified
                End If
                If Me.ETag <> "" Then
                    request.Headers("If-None-Match") = Me.ETag
                End If

                request.CookieContainer = _CookieContainer
                'request.UserAgent = _UserAgent
                request.Timeout = _Timeout

                request.Accept = "*/*"
                request.UserAgent = "Mozilla/5.0" '"OAuth gem v0.4.4"


                'aggiunge gli header della oath 1.0
                If Me.oAuth IsNot Nothing Then
                    Me.oAuth.oauthMethod = request.Method
                    If Not Multipart Then
                        Me.oAuth.additionalHeaderParams = Me.postParams
                    End If
                    Me.oAuth.generateSignature(request)
                    request.Headers.Add(Me.oAuth.getAuthorizationParams())
                End If


                Return request
            End Function
            'Public Shadows Sub UploadString(address As String, data As String)
            '    Dim queryString = HttpUtility.ParseQueryString(data)
            '    For Each param In queryString
            '        postParams.Add(param.Key, param.Value)
            '    Next
            '    MyBase.UploadString(address, data)


            'End Sub
            Protected Overrides Function GetWebResponse(request As WebRequest) As WebResponse
                Dim response As HttpWebResponse




                Try

                    response = MyBase.GetWebResponse(request)

                Catch ex As WebException

                    response = DirectCast(ex.Response, System.Net.HttpWebResponse)

                    If response Is Nothing Then
                        Throw ex
                    End If

                    ' Dim res As System.Net.HttpWebResponse = DirectCast(ex.Response, System.Net.HttpWebResponse)

                    'Dim r = New IO.StreamReader(response.GetResponseStream).ReadToEnd


                End Try

                'Me.LastModified = response.LastModified
                Me.ETag = response.Headers("ETag")

                'Me.ResponseUri = response.ResponseUri
                Me.StatusCode = CInt(response.StatusCode)
                Me.StatusCodeDescr = response.StatusDescription()


                Return response

            End Function

            Private Sub RefreshUserAgent()
                Dim UserAgents As New List(Of String)()
                UserAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)")
                UserAgents.Add("Mozilla/4.0 (compatible; MSIE 8.0; AOL 9.5; AOLBuild 4337.43; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618)")
                UserAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.34; Windows NT 6.0; WOW64; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618)")
                UserAgents.Add("Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8")
                UserAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2a1pre) Gecko/20090402 Firefox/3.6a1pre (.NET CLR 3.5.30729)")
                UserAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4 GTB5 (.NET CLR 3.5.30729)")
                UserAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser; .NET CLR 2.0.50727; MAXTHON 2.0)")
                UserAgents.Add("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; Media Center PC 6.0; InfoPath.2; MS-RTC LM 8)")
                UserAgents.Add("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618)")
                UserAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)")
                UserAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1; Media Center PC 3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)")
                UserAgents.Add("Opera/9.70 (Linux i686 ; U; zh-cn) Presto/2.2.0")
                UserAgents.Add("Opera 9.7 (Windows NT 5.2; U; en)")
                UserAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.8pre) Gecko/20070928 Firefox/2.0.0.7 Navigator/9.0RC1")
                UserAgents.Add("Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.7pre) Gecko/20070815 Firefox/2.0.0.6 Navigator/9.0b3")
                UserAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 5.1; en) AppleWebKit/526.9 (KHTML, like Gecko) Version/4.0dp1 Safari/526.8")
                UserAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 6.0; ru-RU) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16")
                UserAgents.Add("Opera/9.64 (X11; Linux x86_64; U; en) Presto/2.1.1")

                Dim r As New Random()
                Me.UserAgent = UserAgents(r.[Next](0, UserAgents.Count))

                UserAgents = Nothing
            End Sub

            Public Shared Function UrlEncode(value As String) As String
                If String.IsNullOrEmpty(value) Then
                    Return String.Empty
                End If

                value = Uri.EscapeDataString(value)

                ' UrlEncode escapes with lowercase characters (e.g. %2f) but oAuth needs %2F
                value = Regex.Replace(value, "(%[0-9a-f][0-9a-f])", Function(c) c.Value.ToUpper())

                ' these characters are not escaped by UrlEncode() but needed to be escaped
                value = value.Replace("(", "%28").Replace(")", "%29").Replace("$", "%24").Replace("!", "%21").Replace("*", "%2A").Replace("'", "%27")

                ' these characters are escaped by UrlEncode() but will fail if unescaped!
                value = value.Replace("%7E", "~")
                value = value.Replace("%3A", ":")
                value = value.Replace("%09", " ")


                Return value
            End Function
        End Class

        Public Class ExceptionBase
            Inherits Exception

            Public Property ServiceError As ServiceError
            'Public Property webclient As WebClient

            'Public Sub New(webclient As WebClient, ServiceError As ServiceError)

            '    Me.webclient = webclient
            '    Me.ServiceError = ServiceError

            'End Sub

            'Public Sub New()

            'End Sub

            Public Shared Sub ThrowException(ex As Net.ExceptionBase)

                'ex.webclient = webClient
                'ex.ServiceError = LastError

                'Dim WebError = SF("client:{0}, {1} - {3} API ERROR: {2}", webClient.StatusCode, webClient.StatusCodeDescr, LastError.ResError, net.ToString)

                ex.Data.Add("ServiceResponse_Error", ex.ServiceError.ToString)
                ex.Data.Add("ServiceResponse_URL", ex.ServiceError.webClient.RequestUri.AbsolutePath)

                Dim OauthToken = ""

                Select Case ex.ServiceError.Net
                    Case WebApi.Type.TWITTER
                        OauthToken = ex.ServiceError.webClient.oAuth.oauthToken

                    Case Else
                        OauthToken = ex.ServiceError.webClient.oAuth2.access_token

                End Select

                ex.Data.Add("ServiceResponse_oauthToken", OauthToken)

                If ex.GetType = GetType(Net.ExceptionAPIAccount) Then
                    If mDB.Account_Auth.SetErrorAccount(OauthToken) Then
                        UI.Page.WriteLog(SF("DISABLED ACCOUNT {0}", OauthToken))
                    Else
                        UI.Page.WriteLog(SF("ERROR ACCOUNT {0}", OauthToken))
                    End If
                End If

                If ex.ServiceError.AutoProc <> 0 Then
                    MyApp.WriteProcLog(SF("{0} {1}", ex.ServiceError.ToString, ex.ServiceError.webClient.RequestUri.AbsolutePath), ex.ServiceError.AutoProc)
                Else
                    MyApp.WriteProcLog(SF("{0} {1}", ex.ServiceError.ToString, ex.ServiceError.webClient.RequestUri.AbsolutePath), MyApp.Task.TaskType.NET_API)
                    'UI.Page.WriteLog(ex.ServiceError.ToString)
                End If

                Throw ex

            End Sub
        End Class

        '-----------------------------------------
        ' ERRORE SERVER/RETE
        '-----------------------------------------
        Public Class ExceptionConnection
            Inherits ExceptionBase

        End Class

        'errore di connessione
        Public Class ExceptionConnectionNetwork
            Inherits ExceptionConnection

        End Class

        'errore generico del server (5xx)
        Public Class ExceptionConnectionServer
            Inherits ExceptionConnection

        End Class

        '-----------------------------------------
        'ERRORE API
        '-----------------------------------------
        Public Class ExceptionAPI
            Inherits ExceptionBase

        End Class

        'errore account non autorizzato (401)
        Public Class ExceptionAPIAccount
            Inherits ExceptionAPI

        End Class

        'la richiesta non è accessibile (404,403)
        Public Class ExceptionAPIResponse
            Inherits ExceptionAPI

        End Class

        'troppe connessioni per l'account (429)
        Public Class ExceptionAPITooManyRequests
            Inherits ExceptionAPI

        End Class

        'troppe coonessioni usati tutti gli utenti
        Public Class ExceptionTooManyRequestsAllAccount
            Inherits ExceptionBase
        End Class

        ''la richiesta non è accessibile dall'account corrente
        'Public Class ExceptionRequestInvalid
        '    Inherits ExceptionServiceBase

        'End Class


        Public Class ServiceError

            Public Property ResError As String
            Public Property Message As String
            Public Property Code As Integer
            Public Property Net As WebApi.Type
            Public Property webClient As WebClient
            Public Property AutoProc As MyApp.Task.TaskType

            Public Overrides Function ToString() As String
                'Return SF("{0} - {1}", Me.Code, Me.Message)

                Return SF("!!!API ERROR!!! client:{0}, {1} - net:{3} - res: {2}", webClient.StatusCode, webClient.StatusCodeDescr, Me.ResError, Net)

            End Function



        End Class


    End Namespace

End Namespace

